﻿#include <assert.h>
#include <string.h>
#include "tcp_server.h"
static void internal_new_connect(uv_stream_t* stream, int status)
{
	tcp_server* tcpsvr=(tcp_server*)stream->data;
	tcpsvr->process_new_connect(stream,status);
}

static void internal_on_close2(uv_handle_t* handle) {	
	free(handle);
}

tcp_server::tcp_server()
{
}


tcp_server::~tcp_server()
{
	if (_uv_tcp){ free( _uv_tcp); _uv_tcp =NULL;}
}



bool tcp_server::open_listen(char* ip, int port)
{
	_uv_tcp = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
	uv_tcp_init(g_loop, _uv_tcp);
	struct sockaddr_in addr;
	uv_ip4_addr(ip, port, &addr);
	uv_tcp_bind(_uv_tcp, (const struct sockaddr*)&addr, 0);
	_uv_tcp->data = this;
	int r=uv_listen((uv_stream_t*)_uv_tcp, 128, internal_new_connect);
	if (r<0)
		return false;
	_bind_ip = std::string(ip);
	_bind_port = port;
	return true;
}
void tcp_server::process_new_connect(uv_stream_t* stream, int status)
{
	if (status < 0) {		
		return;
	}	
	assert(_conn_rd_cb);
	assert(_new_conncb);
	assert(_conn_closecb);
	uv_tcp_t *client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
	assert(client);
	uv_tcp_init(g_loop, client);

	if (uv_accept(stream, (uv_stream_t*)client) == 0) {
		tcp_connect* conn = new tcp_connect((uv_stream_t*)client);
		client->data = conn;
		_new_conncb(conn);
		uv_read_start((uv_stream_t*)client, internal_on_alloc_buf, internal_on_read);		
		conn->on_bytes_call([=](tcp_connect* tcpconn, char* buf, int bsize){
			_conn_rd_cb(tcpconn,buf,bsize);
		});
		conn->on_close([&](tcp_connect* conn){
			_conn_closecb(conn);
			auto itr=_mp_conn.find(conn);
			if (itr != _mp_conn.end())
				_mp_conn.erase(itr);
			delete conn;
			
		});
		_mp_conn[conn] = conn;
	}
	else {
		uv_close((uv_handle_t*)client, internal_on_close2);
	}

}

void tcp_server::close_listen()
{
	for (auto itr = _mp_conn.begin(); itr != _mp_conn.end();itr++)
	{				
		itr->first->close();		
	}	
}
